![Amazon Managed BlockchainをCloudFormationで作成する](https://devio2023-media.developers.io/wp-content/uploads/2019/04/amazon-managed-blockchain.png)
Amazon Managed BlockchainをCloudFormationで作成する
いわさです。
ブロックチェーンを触っているとスマートコントラクトを気軽に検証したいシーンが多いと思いますが、パブリックブロックチェーンではメインネットだとガスが必要になり、プライベートブロックチェーンでもネットワークやノードのランニングコストが必要になります。
これは、Amazon Managed Blockchainにおいても同様です。
そうなると検証用途としては、パブリックの場合はテストネットなどを利用する、プライベートの場合はリソースを作成したり削除したりを繰り返すことになりますが、非クラウド環境より調達が楽になったとはいえそれでもリソース作成の手順が多かったり待ち時間を何度も挟むことになります。
CloudFormationを使って自動化
Amazon Managed BlockchainはCloudFormationでサポートされているのでテンプレートを用意してみました。
先日、Amazon Managed Blockchain(AMB)でHyperledger Fabricのv2.2を試しましたが、検証環境をすぐ用意できるようにしておきたいと思ったので、AWS側のリソース作成を全てテンプレート化しました。(厳密には、クライアントリソースは今回含めていません)
作成するリソース
作成したテンプレートはこちらへ置いておきます。
このテンプレートでは、フレームワークはHyperledger Fabric v2.2で構成しています。
スタックを作成すると以下のリソースが作成されます。
スタック作成後は以下のネットワーク上にhyperledger/fabric-tools
クライアントなどをデプロイして操作をして頂くイメージです。
ネットワークはパブリックサブネットに配置しているので、適宜テンプレートを調整してください。
リソースの説明
本日時点でAmazon Managed BlockchainのCloudFormationテンプレートの記事はあまり多くないので、この記事では少し構成について触れたいと思います。
現時点でCloudFormationでサポートされているリソースは以下の2つです。
Managed Blockchainを触ったことがある方は、メンバーとノードだけ?と一瞬思うかもしれません。
ネットワーク&メンバー
メンバーリソースではネットワーク構成を指定することが出来ます。
また、ネットワーク構成を指定せずに既存ネットワークIDを指定することで追加メンバーとしてリソースを作成することも可能です。
言われて見ると、Managed Blockchainのネットワーク削除は最後のメンバーを削除することで暗黙的に実行されるので納得出来ます。
NetworkAndInitialMember: Type: "AWS::ManagedBlockchain::Member" Properties: NetworkConfiguration: Name: !Ref NetworkName Framework: "HYPERLEDGER_FABRIC" FrameworkVersion: "2.2" NetworkFrameworkConfiguration: NetworkFabricConfiguration: Edition: !Ref Edition VotingPolicy: ApprovalThresholdPolicy: ThresholdPercentage: !Ref ThresholdPercentage ProposalDurationInHours: !Ref ProposalDurationInHours ThresholdComparator: !Ref ThresholdComparator MemberConfiguration: Name: !Ref MemberName MemberFrameworkConfiguration: MemberFabricConfiguration: AdminUsername: !Ref MemberAdminUsername AdminPassword: !Ref MemberAdminPassword
ノード
ノードについては、インスタンスタイプとAvailability Zoneを指定するだけです。
InitialNode: Type: "AWS::ManagedBlockchain::Node" Properties: NetworkId: !GetAtt NetworkAndInitialMember.NetworkId MemberId: !GetAtt NetworkAndInitialMember.MemberId NodeConfiguration: InstanceType: !Ref InstanceType AvailabilityZone: !Select [ 0, "Fn::GetAZs": {Ref: "AWS::Region"}]
VPCエンドポイント
Managed Blockchainへプライベートアクセスする際には、VPCエンドポイントを利用する必要があります。
リソースから取得できるネットワークIDが大文字で、VPCエンドポイント作成時にエラーになってしまうので、ここではカスタムリソースで作成しました。
AMBのAPIからエンドポイント名を取得しています。
ManagedBlockchainVpcEndpoint: Type: AWS::CloudFormation::CustomResource Properties: ServiceToken: !GetAtt ManagedBlockchainVpcEndpointLambda.Arn NetworkId: !GetAtt NetworkAndInitialMember.NetworkId VpcId: !Ref VPC SubnetIds: - !Ref Subnet1 SecurityGroupIds: - !Ref FabricSecurityGroup ManagedBlockchainVpcEndpointLambda: Type: AWS::Lambda::Function Properties: Code: ZipFile: | import json import boto3 import cfnresponse def handler(event, context): try: print(event) params = dict([(k, v) for k, v in event['ResourceProperties'].items() if k != 'ServiceToken']) amb = boto3.client('managedblockchain') response = amb.get_network( NetworkId=event['ResourceProperties']['NetworkId'] ) vpc_endpoint_service_name = response['Network']['VpcEndpointServiceName'] client = boto3.client('ec2') if event['RequestType'] == 'Create': response = client.create_vpc_endpoint( VpcEndpointType='Interface', VpcId=event['ResourceProperties']['VpcId'], ServiceName=vpc_endpoint_service_name, SubnetIds=event['ResourceProperties']['SubnetIds'], SecurityGroupIds=event['ResourceProperties']['SecurityGroupIds'], PrivateDnsEnabled=True ) cfnresponse.send(event, context, cfnresponse.SUCCESS, {}, 'ManagedBlockchainVpcEndpointLambda') if event['RequestType'] == 'Delete': response = client.describe_vpc_endpoints( Filters=[ { 'Name': 'service-name', 'Values': [ vpc_endpoint_service_name ] }, ], ) response = client.delete_vpc_endpoints( VpcEndpointIds=[ response['VpcEndpoints'][0]['VpcEndpointId'], ] ) cfnresponse.send(event, context, cfnresponse.SUCCESS, {}, 'ManagedBlockchainVpcEndpointLambda') if event['RequestType'] == 'Update': cfnresponse.send(event, context, cfnresponse.FAILED, {}, 'ManagedBlockchainVpcEndpointLambda') except Exception as e: cfnresponse.send(event, context, cfnresponse.FAILED, {}, 'ManagedBlockchainVpcEndpointLambda') Handler: index.handler MemorySize: 128 Role: !GetAtt LambdaExecuteRole.Arn Runtime: python3.9 Timeout: 60
このカスタムリソースは作成と削除は対応していますが、更新は考慮できていないのでご注意ください。
さいごに
本日はAmazon Managed BlockchainのCloudFormationテンプレートサンプルを紹介しました。
実際にはこの上にのるクライアントを使って証明書やチャネル、チェーンコードの準備がさらに大変なので、そのあたりも自動化できるようにしたいと思います。